package com.ilxqx.framework.generator.core.mysql;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ilxqx.framework.generator.cast.MysqlTypeToJavaType;
import com.ilxqx.framework.generator.constant.GenerationConfigConstants;
import com.ilxqx.framework.generator.core.ModelData;
import com.ilxqx.framework.generator.core.RawTableInfoParser;
import com.ilxqx.framework.generator.core.TableInfoParser;
import com.ilxqx.framework.generator.data.DataModelProcessing;
import com.ilxqx.framework.generator.data.ProcessingOrder;
import com.ilxqx.framework.generator.parser.Table;
import com.ilxqx.framework.generator.po.RawTable;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

/**
 * mysql 模型数据
 * @author venus
 */
@Slf4j
public class MysqlModelData implements ModelData {

	/**
	 * 根据表名获取模型数据
	 *
	 * @param tableName 表名
	 * @return 模型数据
	 */
	@Override
	public Map<String, Object> getModelData(String tableName) {
		// 解析原始信息
		RawTableInfoParser rawTableInfoParser = new MysqlRawTableInfoParser();
		RawTable rawTable = rawTableInfoParser.perform(tableName);
		// 解析加工信息
		TableInfoParser tableInfoParser = new MysqlTableInfoParser(new MysqlTypeToJavaType());
		Table table = tableInfoParser.parseTableInfo(rawTable);
		// 组装返回
		Map<String, Object> data = Maps.newHashMap();
		data.put("table", table);
		data.put("frameworkPackage", GenerationConfigConstants.FRAMEWORK_PACKAGE);
		data.put("basePackage", GenerationConfigConstants.BASE_PACKAGE);
		data.put("requestUriName", GenerationConfigConstants.REQUEST_URI_NAME);
		// 执行数据处理器
		this.processData(data);
		return data;
	}

	/**
	 * 加工数据
	 * @param data 数据模型
	 */
	private void processData(Map<String, Object> data) {
		String[] dataProcessorClasses = GenerationConfigConstants.DATA_PROCESSORS;
		// 加载类并创建对象
		List<DataModelProcessing> dataModelProcessingList = loadProcessorClasses(dataProcessorClasses);
		// 对它们进行排序
		this.sort(dataModelProcessingList);
		// 调用
		for (DataModelProcessing dataModelProcessing : dataModelProcessingList) {
			dataModelProcessing.process(data);
		}
	}

	/**
	 * 处理排序
	 * @param dataModelProcessingList 处理器列表
	 */
	private void sort(List<DataModelProcessing> dataModelProcessingList) {
		dataModelProcessingList.sort((o1, o2) -> {
			int order1 = 10, order2 = 10;
			if (o1.getClass().isAnnotationPresent(ProcessingOrder.class)) {
				order1 = o1.getClass().getAnnotation(ProcessingOrder.class).value();
			}
			if (o2.getClass().isAnnotationPresent(ProcessingOrder.class)) {
				order2 = o2.getClass().getAnnotation(ProcessingOrder.class).value();
			}
			return order1 - order2;
		});
	}

	/**
	 * 加载处理器类并实例化
	 * @param dataProcessorClasses 处理器类全路径
	 * @return 处理器实例列表
	 */
	private List<DataModelProcessing> loadProcessorClasses(String[] dataProcessorClasses) {
		List<DataModelProcessing> dataModelProcessingList = Lists.newArrayList();
		for (String dataProcessorClass : dataProcessorClasses) {
			Class<?> cls;
			try {
				cls = Class.forName(dataProcessorClass);
			} catch (ClassNotFoundException e) {
				// 数据处理器不存在，忽略
				log.warn("数据处理器[{}]不存在", dataProcessorClass);
				continue;
			}
			// 创建cls实例
			try {
				Object instance = cls.getDeclaredConstructor().newInstance();
				dataModelProcessingList.add((DataModelProcessing) instance);
			} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
				log.warn("数据处理器[{}]实例化失败，很有可能是你没有给它提供无参构造造成的，请仔细检查", dataProcessorClass);
			}
		}
		return dataModelProcessingList;
	}

}
